package com.yanqu.road.dao.impl.activity.twins;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.TypeReference;
import com.yanqu.road.dao.db.DbNameStrategy;
import com.yanqu.road.dao.db.DbParameter;
import com.yanqu.road.dao.impl.TempDao;
import com.yanqu.road.entity.activity.twins.CrossTwinsBossData;
import com.yanqu.road.entity.activity.twins.CrossTwinsDamageRecordData;
import com.yanqu.road.entity.activity.twins.CrossTwinsUserData;
import com.yanqu.road.utils.string.StringUtils;

import java.math.BigInteger;
import java.sql.CallableStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

public class CrossTwinsDataDaoImpl extends TempDao {
    //boss
    public int getMaxBossNo(int activityId,int groupId) {
        String sql = "select max(bossNo) as bossNo from t_c_activity_twins_boss where activityId=? and groupId=?";
        ResultSet rs = null;
        CallableStatement call = null;
        try {
            getDb().setConnName(DbNameStrategy.getCross2Db());
            call = getDb().getConnection().prepareCall(sql);
            int i = 1;
            call.setInt(i++,activityId);
            call.setInt(i++,groupId);
            rs = call.executeQuery();
            while (rs.next()) {
                int data = rs.getInt("bossNo");
                if(data == 0){
                    return 1;
                }
                return data + 1;
            }
        } catch (Exception e) {
            throw new RuntimeException(e);} finally {
            getDb().closeConnection(call, rs);
        }
        return 1;
    }

    public int getMaxUserNo(int activityId,int groupId) {
        String sql = "select max(userNo) as userNo from t_c_activity_twins_user where activityId=? and groupId=?";
        ResultSet rs = null;
        CallableStatement call = null;
        try {
            getDb().setConnName(DbNameStrategy.getCross2Db());
            call = getDb().getConnection().prepareCall(sql);
            int i = 1;
            call.setInt(i++,activityId);
            call.setInt(i++,groupId);
            rs = call.executeQuery();
            while (rs.next()) {
                int data = rs.getInt("userNo");
                if(data == 0){
                    return 1;
                }
                return data + 1;
            }
        } catch (Exception e) {
            throw new RuntimeException(e);} finally {
            getDb().closeConnection(call, rs);
        }
        return 1;
    }

    public Map<Integer,CrossTwinsBossData> getBossDataList(int activityId,int groupId) {
        Map<Integer,CrossTwinsBossData> dataMap = new ConcurrentHashMap<>();
        ResultSet rs = null;
        CallableStatement call = null;
        String sql = "SELECT * FROM t_c_activity_twins_boss WHERE activityId = ? AND groupId = ? AND dieTime = 0";
        try {
            getDb().setConnName(DbNameStrategy.getCrossDb());
            call = getDb().getConnection().prepareCall(sql);
            int i = 1;
            call.setInt(i++,activityId);
            call.setInt(i++,groupId);
            rs = call.executeQuery();
            while (rs.next()) {
                CrossTwinsBossData data = initBossData(rs);
                dataMap.put(data.getBossId(),data);
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            getDb().closeConnection(call, rs);
        }
        return dataMap;
    }

    protected  CrossTwinsBossData initBossData(ResultSet rs) throws SQLException {
        CrossTwinsBossData data = new  CrossTwinsBossData();
        data.setActivityId(rs.getInt("activityId"));
        data.setGroupId(rs.getInt("groupId"));
        data.setBossNo(rs.getInt("bossNo"));
        data.setBossId(rs.getInt("bossId"));
        data.setBool(new BigInteger(rs.getString("bool")));
        data.setStartTime(rs.getLong("startTime"));
        data.setDieTimes(rs.getInt("dieTimes"));
        data.setDieTime(rs.getLong("dieTime"));
        
        return data;
    }

    public boolean addBossDataList(List<CrossTwinsBossData> dataList) {
        String sql = "insert into t_c_activity_twins_boss(" +
                " activityId,groupId,bossNo,bossId,bool,startTime,dieTimes,dieTime" +
                " ) " +
                " values (?,?,?,?,?,?,?,?)";
        try {
            getDb().setConnName(DbNameStrategy.getCross2Db());
            List<Map<Integer, DbParameter>> mapList = new ArrayList<>();
            for (CrossTwinsBossData data : dataList) {
                int i = 1;
                Map<Integer, DbParameter> para = new HashMap<>();
                para.put(i++, new DbParameter(Types.INTEGER,  data.getActivityId()));
                para.put(i++, new DbParameter(Types.INTEGER,  data.getGroupId()));
                para.put(i++, new DbParameter(Types.INTEGER,  data.getBossNo()));
                para.put(i++, new DbParameter(Types.INTEGER,  data.getBossId()));
                para.put(i++, new DbParameter(Types.VARCHAR,  data.getBool().toString()));
                para.put(i++, new DbParameter(Types.BIGINT,  data.getStartTime()));
                para.put(i++, new DbParameter(Types.INTEGER,  data.getDieTimes()));
                para.put(i++, new DbParameter(Types.BIGINT,  data.getDieTime()));
                mapList.add(para);
            }
            if (getDb().executeBatchQuery(sql, mapList) > -1) {
                return true;
            }
        } catch (Exception e) {
            logger.error(Thread.currentThread().getStackTrace()[1].getMethodName() + ":", e);
        }
        return false;
    }

    public boolean updateBossDataList(List<CrossTwinsBossData> dataList) {
        String sql = "UPDATE t_c_activity_twins_boss SET " +
                " bool=?,startTime=?,dieTimes=?,dieTime=?" +
                " WHERE activityId=? and groupId=? and bossNo = ?";
        try {
            getDb().setConnName(DbNameStrategy.getCross2Db());
            List<Map<Integer, DbParameter>> mapList = new ArrayList<>();
            for (CrossTwinsBossData  data : dataList) {
                int i = 1;
                Map<Integer, DbParameter> para = new HashMap<>();
                para.put(i++, new DbParameter(Types.VARCHAR,  data.getBool().toString()));
                para.put(i++, new DbParameter(Types.BIGINT,  data.getStartTime()));
                para.put(i++, new DbParameter(Types.INTEGER,  data.getDieTimes()));
                para.put(i++, new DbParameter(Types.BIGINT,  data.getDieTime()));
                para.put(i++, new DbParameter(Types.INTEGER,  data.getActivityId()));
                para.put(i++, new DbParameter(Types.INTEGER,  data.getGroupId()));
                para.put(i++, new DbParameter(Types.INTEGER,  data.getBossNo()));
                mapList.add(para);
            }
            if (getDb().executeBatchQuery(sql, mapList) > -1) {
                return true;
            }
        } catch (Exception e) {
            logger.error(Thread.currentThread().getStackTrace()[1].getMethodName() + ":", e);
        }
        return false;
    }

    //user
    public Map<Long,CrossTwinsUserData> getUserDataList(int activityId,int groupId) {
        Map<Long,CrossTwinsUserData> dataMap = new ConcurrentHashMap<>();
        ResultSet rs = null;
        CallableStatement call = null;
        String sql = "SELECT * FROM t_c_activity_twins_user WHERE activityId = ? and groupId = ?";
        try {
            getDb().setConnName(DbNameStrategy.getCrossDb());
            call = getDb().getConnection().prepareCall(sql);
            int i = 1;
            call.setInt(i++,activityId);
            call.setInt(i++,groupId);
            rs = call.executeQuery();
            while (rs.next()) {
                CrossTwinsUserData data = initUserData(rs);
                dataMap.put(data.getUserId(),data);
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            getDb().closeConnection(call, rs);
        }
        return dataMap;
    }

    protected  CrossTwinsUserData initUserData(ResultSet rs) throws SQLException {
        CrossTwinsUserData data = new  CrossTwinsUserData();
        data.setActivityId(rs.getInt("activityId"));
        data.setGroupId(rs.getInt("groupId"));
        data.setBossId(rs.getInt("bossId"));
        data.setHp(rs.getInt("hp"));
        data.setHpTime(rs.getLong("hpTime"));
        data.setUserNo(rs.getInt("userNo"));
        data.setUserId(rs.getLong("userId"));
        data.setAttackUserId(rs.getLong("attackUserId"));
        data.setStatus(rs.getInt("status"));
        data.setMaxBool(new BigInteger(rs.getString("maxBool")));
        data.setMaxAttack(new BigInteger(rs.getString("maxAttack")));
        data.setRoomMaxBool(new BigInteger(rs.getString("roomMaxBool")));
        data.setRoomBool(new BigInteger(rs.getString("roomBool")));
        data.setRoomAttack(new BigInteger(rs.getString("roomAttack")));
        data.setAttackScore(rs.getLong("attackScore"));
        data.setAllScore(rs.getLong("allScore"));
        data.setAttackTime(rs.getLong("attackTime"));
        data.setLastAttackTime(rs.getLong("lastAttackTime"));
        data.setReward(rs.getString("reward"));
        data.setKillReward(rs.getString("killReward"));
        data.setKillUserId(rs.getLong("killUserId"));
        data.setKillBossUserId(rs.getLong("killBossUserId"));
        data.setKillBossId(rs.getInt("killBossId"));
        data.setDrawTimes(rs.getInt("drawTimes"));
        data.setDrawNoBigCount(rs.getInt("drawNoBigCount"));
        data.setLastDrawItemId(rs.getInt("lastDrawItemId"));
        data.setKillTimes(rs.getInt("killTimes"));

        String drawItemListStr  = rs.getString("drawItemList");
        if(!StringUtils.isNullOrEmpty(drawItemListStr)){
            List<Integer> result = JSON.parseObject(drawItemListStr, new TypeReference<List<Integer>>() {});
            if(result != null){
                data.setDrawItemList(result);
            }
        }
        return data;
    }

    public boolean addUserDataList(List<CrossTwinsUserData> dataList) {
        String sql = "insert into t_c_activity_twins_user(" +
                " activityId,groupId,bossId,hp,hpTime,userNo,userId,attackUserId,status,maxBool,maxAttack,roomMaxBool,roomBool,roomAttack,attackScore," +
                " allScore,attackTime,lastAttackTime,reward,killReward,killUserId,drawTimes,drawNoBigCount,drawItemList,lastDrawItemId,killTimes,killBossUserId,killBossId,lastBossId" +
                " ) " +
                " values (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
        try {
            getDb().setConnName(DbNameStrategy.getCross2Db());
            List<Map<Integer, DbParameter>> mapList = new ArrayList<>();
            for (CrossTwinsUserData data : dataList) {
                int i = 1;
                Map<Integer, DbParameter> para = new HashMap<>();
                para.put(i++, new DbParameter(Types.INTEGER,  data.getActivityId()));
                para.put(i++, new DbParameter(Types.INTEGER,  data.getGroupId()));
                para.put(i++, new DbParameter(Types.INTEGER,  data.getBossId()));
                para.put(i++, new DbParameter(Types.INTEGER,  data.getHp()));
                para.put(i++, new DbParameter(Types.BIGINT,  data.getHpTime()));
                para.put(i++, new DbParameter(Types.INTEGER,  data.getUserNo()));
                para.put(i++, new DbParameter(Types.BIGINT,  data.getUserId()));
                para.put(i++, new DbParameter(Types.BIGINT,  data.getAttackUserId()));
                para.put(i++, new DbParameter(Types.INTEGER,  data.getStatus()));
                para.put(i++, new DbParameter(Types.VARCHAR,  data.getMaxBool().toString()));
                para.put(i++, new DbParameter(Types.VARCHAR,  data.getMaxAttack().toString()));
                para.put(i++, new DbParameter(Types.VARCHAR,  data.getRoomMaxBool().toString()));
                para.put(i++, new DbParameter(Types.VARCHAR,  data.getRoomBool().toString()));
                para.put(i++, new DbParameter(Types.VARCHAR,  data.getRoomAttack().toString()));
                para.put(i++, new DbParameter(Types.BIGINT,  data.getAttackScore()));
                para.put(i++, new DbParameter(Types.BIGINT,  data.getAllScore()));
                para.put(i++, new DbParameter(Types.BIGINT,  data.getAttackTime()));
                para.put(i++, new DbParameter(Types.BIGINT,  data.getLastAttackTime()));
                para.put(i++, new DbParameter(Types.VARCHAR,  data.getReward()));
                para.put(i++, new DbParameter(Types.VARCHAR,  data.getKillReward()));
                para.put(i++, new DbParameter(Types.BIGINT,  data.getKillUserId()));
                para.put(i++, new DbParameter(Types.INTEGER,  data.getDrawTimes()));
                para.put(i++, new DbParameter(Types.INTEGER,  data.getDrawNoBigCount()));
                para.put(i++, new DbParameter(Types.VARCHAR,  JSONArray.toJSONString(data.getDrawItemList())));
                para.put(i++, new DbParameter(Types.INTEGER,  data.getLastDrawItemId()));
                para.put(i++, new DbParameter(Types.INTEGER,  data.getKillTimes()));
                para.put(i++, new DbParameter(Types.BIGINT,  data.getKillBossUserId()));
                para.put(i++, new DbParameter(Types.INTEGER,  data.getKillBossId()));
                para.put(i++, new DbParameter(Types.INTEGER,  data.getLastBossId()));


                mapList.add(para);
            }
            if (getDb().executeBatchQuery(sql, mapList) > -1) {
                return true;
            }
        } catch (Exception e) {
            logger.error(Thread.currentThread().getStackTrace()[1].getMethodName() + ":", e);
        }
        return false;
    }

    public boolean updateUserDataList(List<CrossTwinsUserData> dataList) {
        String sql = "UPDATE t_c_activity_twins_user SET " +
                " userNo=?,bossId=?,hp=?,hpTime=?,attackUserId=?,status=?,maxBool=?,maxAttack=?,roomMaxBool=?,roomBool=?," +
                " roomAttack=?,attackScore=?,allScore=?,attackTime=?,lastAttackTime=?,reward=?,killReward=?,killUserId=?," +
                " drawTimes=?,drawNoBigCount=?,drawItemList=?,lastDrawItemId=?,killTimes=?,killBossUserId=?,killBossId=?,lastBossId=?" +
                " WHERE activityId=? and groupId=? and userId = ?";
        try {
            getDb().setConnName(DbNameStrategy.getCross2Db());
            List<Map<Integer, DbParameter>> mapList = new ArrayList<>();
            for (CrossTwinsUserData  data : dataList) {
                int i = 1;
                Map<Integer, DbParameter> para = new HashMap<>();
                para.put(i++, new DbParameter(Types.INTEGER,  data.getUserNo()));
                para.put(i++, new DbParameter(Types.INTEGER,  data.getBossId()));
                para.put(i++, new DbParameter(Types.INTEGER,  data.getHp()));
                para.put(i++, new DbParameter(Types.BIGINT,  data.getHpTime()));
                para.put(i++, new DbParameter(Types.BIGINT,  data.getAttackUserId()));
                para.put(i++, new DbParameter(Types.INTEGER,  data.getStatus()));
                para.put(i++, new DbParameter(Types.VARCHAR,  data.getMaxBool().toString()));
                para.put(i++, new DbParameter(Types.VARCHAR,  data.getMaxAttack().toString()));
                para.put(i++, new DbParameter(Types.VARCHAR,  data.getRoomMaxBool().toString()));
                para.put(i++, new DbParameter(Types.VARCHAR,  data.getRoomBool().toString()));
                para.put(i++, new DbParameter(Types.VARCHAR,  data.getRoomAttack().toString()));
                para.put(i++, new DbParameter(Types.BIGINT,  data.getAttackScore()));
                para.put(i++, new DbParameter(Types.BIGINT,  data.getAllScore()));
                para.put(i++, new DbParameter(Types.BIGINT,  data.getAttackTime()));
                para.put(i++, new DbParameter(Types.BIGINT,  data.getLastAttackTime()));
                para.put(i++, new DbParameter(Types.VARCHAR,  data.getReward()));
                para.put(i++, new DbParameter(Types.VARCHAR,  data.getKillReward()));
                para.put(i++, new DbParameter(Types.BIGINT,  data.getKillUserId()));
                para.put(i++, new DbParameter(Types.INTEGER,  data.getDrawTimes()));
                para.put(i++, new DbParameter(Types.INTEGER,  data.getDrawNoBigCount()));
                para.put(i++, new DbParameter(Types.VARCHAR,  JSONArray.toJSONString(data.getDrawItemList())));
                para.put(i++, new DbParameter(Types.INTEGER,  data.getLastDrawItemId()));
                para.put(i++, new DbParameter(Types.INTEGER,  data.getKillTimes()));
                para.put(i++, new DbParameter(Types.BIGINT,  data.getKillBossUserId()));
                para.put(i++, new DbParameter(Types.INTEGER,  data.getKillBossId()));
                para.put(i++, new DbParameter(Types.INTEGER,  data.getLastBossId()));

                para.put(i++, new DbParameter(Types.INTEGER,  data.getActivityId()));
                para.put(i++, new DbParameter(Types.INTEGER,  data.getGroupId()));
                para.put(i++, new DbParameter(Types.BIGINT,  data.getUserId()));
                mapList.add(para);
            }
            if (getDb().executeBatchQuery(sql, mapList) > -1) {
                return true;
            }
        } catch (Exception e) {
            logger.error(Thread.currentThread().getStackTrace()[1].getMethodName() + ":", e);
        }
        return false;
    }


    //record
    public List<CrossTwinsDamageRecordData> getDamageRecordDataList(int activityId,int groupId,List<Integer> bossNoList) {
        List<CrossTwinsDamageRecordData> dataList = new ArrayList<>();
        if(bossNoList.size() == 0){
            return dataList;
        }
        Collections.sort(bossNoList);
        int minBossNo = bossNoList.get(bossNoList.size() - 1);
        String inStr = StringUtils.listToString(bossNoList,",");
        ResultSet rs = null;
        CallableStatement call = null;
        String sql = "SELECT * FROM t_c_activity_twins_damage_record WHERE activityId = ? AND groupId=? AND bossNo <= ? AND bossNo >= ?";
        try {
            getDb().setConnName(DbNameStrategy.getCrossDb());
            call = getDb().getConnection().prepareCall(sql);
            int i = 1;
            call.setInt(i++,activityId);
            call.setInt(i++,groupId);
            call.setInt(i++,minBossNo);
            //取bossId最小的前10个号码吧
            call.setInt(i++,minBossNo - 20);
            rs = call.executeQuery();
            while (rs.next()) {
                CrossTwinsDamageRecordData data = initDamageRecordData(rs);
                dataList.add(data);
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            getDb().closeConnection(call, rs);
        }
        return dataList;
    }

    protected  CrossTwinsDamageRecordData initDamageRecordData(ResultSet rs) throws SQLException {
        CrossTwinsDamageRecordData data = new  CrossTwinsDamageRecordData();
        data.setActivityId(rs.getInt("activityId"));
        data.setGroupId(rs.getInt("groupId"));
        data.setBossNo(rs.getInt("bossNo"));
        data.setBossId(rs.getInt("bossId"));
        data.setUserId(rs.getLong("userId"));
        data.setAttackUserId(rs.getLong("attackUserId"));
        data.setDamage(new BigInteger(rs.getString("damage")));
        data.setAttackUserId(rs.getLong("attackUserId"));
        data.setStartTime(rs.getLong("startTime"));
        data.setScore(rs.getLong("score"));
        data.setUserNo(rs.getInt("userNo"));
        data.setAttackUserNo(rs.getInt("attackUserNo"));
        data.setKill(rs.getBoolean("isKill"));

        return data;
    }

    public boolean addDamageRecordDataList(List<CrossTwinsDamageRecordData> dataList) {
        String sql = "insert into t_c_activity_twins_damage_record(" +
                " activityId,groupId,bossNo,bossId,userId,attackUserId,damage,startTime,score,userNo,attackUserNo,isKill" +
                " ) " +
                " values (?,?,?,?,?,?,?,?,?,?,?,?)";
        try {
            getDb().setConnName(DbNameStrategy.getCross2Db());
            List<Map<Integer, DbParameter>> mapList = new ArrayList<>();
            for (CrossTwinsDamageRecordData data : dataList) {
                int i = 1;
                Map<Integer, DbParameter> para = new HashMap<>();
                para.put(i++, new DbParameter(Types.INTEGER,  data.getActivityId()));
                para.put(i++, new DbParameter(Types.INTEGER,  data.getGroupId()));
                para.put(i++, new DbParameter(Types.INTEGER,  data.getBossNo()));
                para.put(i++, new DbParameter(Types.INTEGER,  data.getBossId()));
                para.put(i++, new DbParameter(Types.BIGINT,  data.getUserId()));
                para.put(i++, new DbParameter(Types.BIGINT,  data.getAttackUserId()));
                para.put(i++, new DbParameter(Types.VARCHAR,  data.getDamage().toString()));
                para.put(i++, new DbParameter(Types.BIGINT,  data.getStartTime()));
                para.put(i++, new DbParameter(Types.BIGINT,  data.getScore()));
                para.put(i++, new DbParameter(Types.INTEGER,  data.getUserNo()));
                para.put(i++, new DbParameter(Types.INTEGER,  data.getAttackUserNo()));
                para.put(i++, new DbParameter(Types.BOOLEAN,  data.isKill()));
                mapList.add(para);
            }
            if (getDb().executeBatchQuery(sql, mapList) > -1) {
                return true;
            }
        } catch (Exception e) {
            logger.error(Thread.currentThread().getStackTrace()[1].getMethodName() + ":", e);
        }
        return false;
    }

    public boolean updateDamageRecordDataList(List<CrossTwinsDamageRecordData> dataList) {
        String sql = "UPDATE t_c_activity_twins_damage_record SET " +
                " damage=?,startTime=?,score=?,isKill=?" +
                " WHERE activityId=? and groupId=? and bossNo=? and userNo = ? and attackUserNo = ?";
        try {
            getDb().setConnName(DbNameStrategy.getCross2Db());
            List<Map<Integer, DbParameter>> mapList = new ArrayList<>();
            for (CrossTwinsDamageRecordData  data : dataList) {
                int i = 1;
                Map<Integer, DbParameter> para = new HashMap<>();
                para.put(i++, new DbParameter(Types.VARCHAR,  data.getDamage().toString()));
                para.put(i++, new DbParameter(Types.BIGINT,  data.getStartTime()));
                para.put(i++, new DbParameter(Types.BIGINT,  data.getScore()));
                para.put(i++, new DbParameter(Types.BOOLEAN,  data.isKill()));

                para.put(i++, new DbParameter(Types.INTEGER,  data.getActivityId()));
                para.put(i++, new DbParameter(Types.INTEGER,  data.getGroupId()));
                para.put(i++, new DbParameter(Types.INTEGER,  data.getBossNo()));
                para.put(i++, new DbParameter(Types.INTEGER,  data.getUserNo()));
                para.put(i++, new DbParameter(Types.INTEGER,  data.getAttackUserNo()));
                mapList.add(para);
            }
            if (getDb().executeBatchQuery(sql, mapList) > -1) {
                return true;
            }
        } catch (Exception e) {
            logger.error(Thread.currentThread().getStackTrace()[1].getMethodName() + ":", e);
        }
        return false;
    }
}
